package com.senyint.imsdk.listener;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.util.StringUtils;

import com.senyint.imsdk.SendPacketException;
import com.senyint.imsdk.packet.AttachmentPacketExtension;
import com.senyint.imsdk.packet.DeliveryRecv;
import com.senyint.imsdk.packet.DeliveryRecvRequest;
import com.senyint.imsdk.packet.DeliverySent;
import com.senyint.imsdk.util.PacketUtil;

public abstract class XMPPMessageListener implements PacketListener {
	private ExecutorService receiveExecutorService = null ;
	public XMPPMessageListener(){
		final String threadId = "message-"+StringUtils.randomString(6);
		receiveExecutorService = Executors.newSingleThreadExecutor(new ThreadFactory() {
					@Override
					public Thread newThread(Runnable runnable) {
						Thread thread = new Thread(
								runnable,
								"Connection Thread for Reveiving  " + threadId );
						thread.setPriority(Thread.MIN_PRIORITY);
						thread.setDaemon(true);
						return thread;
					}
				});
	}
	
	@Override
	public void processPacket(Packet packet) {
		System.out.println("Packet recv:"+packet.toXML());
		onHandleMessage((Message)packet);
	}

	public void onHandleMessage(Message message) {
		if(Message.Type.error.equals(message.getType())){
			onHandleErrorMessage(message);
		}else{
			String messageID = message.getPacketID();
			
			//服务器发送回执,表示发送的消息已经到达服务器
			PacketExtension sentPE = message.getExtension(DeliverySent.ELEMENT, DeliverySent.NAMESPACE);
			if(sentPE != null&&sentPE.toXML().indexOf("key")!=-1){
				DeliverySent ds  = DeliverySent.parse(sentPE.toXML());
				if(ds!=null&&ds.getId()!=null){
					onUpdateSentMessage(ds.getId());
		//			return ;
				}
			}
			
			//判断是否有回执消息，表示自己发的消息已经被对方收到
	   	 	PacketExtension recvPe = message.getExtension(DeliveryRecv.ELEMENT,DeliveryRecv.NAMESPACE);
	        if (recvPe != null) {
	        	recvPe = DeliveryRecv.parse(recvPe.toXML());
		        	 onUpdateReceivedMessageState(((DeliveryRecv)recvPe).getId());
	//	        return ;
	        }
	
			//发送方请求回执消息,如果有，表示发送方需要接收方接收到之后回复发送人
	        PacketExtension mreq = message.getExtension(DeliveryRecvRequest.ELEMENT,DeliveryRecvRequest.NAMESPACE);
	        if (mreq != null) {
	        	onReplyReceiver(message);
	        }
	        
			if (message.getConversation() == null && message.getFromNode()!=null) {
				String convs = PacketUtil.createConversationID(message.getToNode(),message.getFromNode(), message.getTopic());
				if(convs != null)
					message.setConversation(convs);
			}
			
			String body = message.getBody();
			PacketExtension ape = message.getExtension(AttachmentPacketExtension.ELEMENT_NAME, AttachmentPacketExtension.NAMESPACE);
	        if (ape != null) {
	        	ape = AttachmentPacketExtension.parse(ape.toXML());
	        }
	        
	        if((message.getType()== Message.Type.chat || message.getType()== Message.Type.groupchat )
	        		 && ( body !=null || ape != null ) )
	        	onFeedbackServer(messageID);
			
			onNotifyIncomingMessage(message);
		}
	}
	
	/**
	 * 反馈给服务器消息已经收到
	 * @param messageID
	 */
	public abstract void onFeedbackServer(final String messageID) ;


	/**
	 * 处理错误类型消息
	 * @param message
	 */
	public void onHandleErrorMessage(Message message) {
	}


	/**
	 * 通知有新消息到来<br>
	 * 	默认只通知有内容和扩展消息的消息
	 * @param message
	 */
	public void onNotifyIncomingMessage(Message message) {
        
	}
	

	/**
	 * 回复发送人，该消息已经收到
	 * @param message
	 */
	public void onReplyReceiver(Message message) {
		//回复别人
    	Message backMsg = new Message();
    	backMsg.setType(Message.Type.normal);
    	backMsg.setTo(message.getFrom());
    	backMsg.addExtension(new DeliveryRecv(message.getPacketID()));
    	try {
			sendPacket(backMsg);
		} catch (SendPacketException e) {
		}		
	}

	public abstract void sendPacket(Packet packet) throws SendPacketException ;

	/**
	 * 更新本地消息，标识对方已经收到
	 * @param id
	 */
	public void onUpdateReceivedMessageState(String packetID) {
	}
	
	/**
	 * 更改发送记录，标识该消息已经发送成功
	 * @param packetID
	 */
	public void onUpdateSentMessage(String packetID) {
	}
	
	public void onHandleInBackgroud(Runnable r){
		receiveExecutorService.execute(r);
	}
	
}

